package com.zk.config.api.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;
import org.apache.log4j.Logger;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Stat;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import com.zk.config.api.constants.Constants;

public class ZkOperate {
	
	private static Logger logger = Logger.getLogger(ZkOperate.class);

	/**
	 * 删除一个节点
	 * @param zk
	 * @param path
	 */
	public static boolean deleteNode(ZooKeeper zk, String path) {
		boolean result = false;
		try {
			zk.delete(path,-1);
			result = true;
		} catch (InterruptedException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		} catch (KeeperException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		}
		return result;
	}
	
	/**
	 * 级联删除节点
	 * @param zk
	 * @param path
	 */
	public static void deleteAllNode(ZooKeeper zk, String path) {
		try {
			if (existsNode(zk, path) != null) {
				List<String> list = zk.getChildren(path, false);
				if(list != null && list.size() > 0) {
					for(String c:list) {
						String cpath = "/".equals(path)?(path+c):(path + ZkCom.getZkPath(c));
						deleteAllNode(zk, cpath);
					}
				}
				deleteNode(zk, path);
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		} catch (KeeperException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		}
	}
	
	/**
	 * 根据mpa提供的path->value数据删除所有节点（使用级联删除）
	 * @param zk
	 * @param map
	 */
	public static void deleteAllNodeByMap(ZooKeeper zk, Map<String, byte[]> map) {
		if(map != null && map.size() > 0) {
			for(String key:map.keySet()) {
				deleteAllNode(zk, key);
			}
		}
	}
	
	/**
	 * 创建一个节点
	 * @param zk
	 * @param path
	 */
	public static boolean createNode(ZooKeeper zk, String path) {
		boolean result = false;
		try {
			zk.create(path, null, Ids.OPEN_ACL_UNSAFE,
					   CreateMode.PERSISTENT);
			result = true;
		} catch (KeeperException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		} catch (InterruptedException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		}
		return result;
	}
	
	/**
	 * 创建一个有内容的节点
	 * @param zk
	 * @param path
	 * @param content
	 * @return
	 */
	public static boolean createNode(ZooKeeper zk, String path, String content) {
		boolean result = false;
		byte[] b = content == null?null:content.getBytes(Constants.defualtCharset);
		try {
			zk.create(path, b, Ids.OPEN_ACL_UNSAFE,
					   CreateMode.PERSISTENT);
			result = true;
		} catch (KeeperException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		} catch (InterruptedException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		}
		return result;
	}
	
	/**
	 * 创建一个节点
	 * @param zk
	 * @param path
	 * @param content
	 * @return
	 */
	public static boolean createNode(ZooKeeper zk, String path, byte[] content) {
		boolean result = false;
		try {
			zk.create(path, content, Ids.OPEN_ACL_UNSAFE,
					   CreateMode.PERSISTENT);
			result = true;
		} catch (KeeperException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		} catch (InterruptedException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		}
		return result;
	}
	
	/**
	 * 创建一个带授权信息的节点
	 * @param zk
	 * @param path
	 * @param content
	 * @param acls
	 * @return
	 */
	public static boolean createNode(ZooKeeper zk, String path, byte[] content, List<ACL> acls) {
		boolean result = false;
		try {
			zk.create(path, content, acls,
					   CreateMode.PERSISTENT);
			result = true;
		} catch (KeeperException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		} catch (InterruptedException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		}
		return result;
	}
	
	/**
	 * 级联创建创建一个节点
	 * @param zk
	 * @param path
	 * @param content
	 * @return
	 */
	public static boolean createAllNode(ZooKeeper zk, String path, byte[] content) {
		boolean result = false;
		int index = -1;
		if(path != null && (index = path.lastIndexOf("/")) != -1 && !"/".equals(path)) {
			String parentpath = path.substring(0, index);
			if(parentpath != null && parentpath.length() > 0 && existsNode(zk, parentpath) == null) {
				result = createAllNode(zk, parentpath, null);
				if (!result) {
					return result;
				}
			}

			result = createNode(zk, path, content);
		}
		return result;
	}
	
	/**
	 * 根据mpa提供的path->value数据创建所有节点（递归创建不存在的父节点），失败提供回滚数据的map
	 * @param zk
	 * @param map
	 * @param okMap
	 * @return
	 */
	public static boolean createAllNodeByMap(ZooKeeper zk, Map<String, byte[]> map, Map<String, byte[]> okMap) {
		boolean result = false;
		if(map != null && map.size() > 0) {
			for(String key:map.keySet()) {
				result = createAllNode(zk, key, map.get(key));
				if(!result) {
					return result;
				} else {
					if (okMap != null) {
						okMap.put(key, map.get(key));
					}
				}
			}
			result = true;
		}
		return result;
	}
	
	/**
	 * 还原一个节点，父节点不存在则创建，失败提供回滚数据用的map
	 * @param zk
	 * @param path
	 * @param content
	 * @param createOkMap
	 * @param oldDataMap
	 * @param isRecover
	 * @return
	 */
	public static boolean recoverAllNode(ZooKeeper zk, String path, byte[] content, Map<String, byte[]> createOkMap, Map<String, byte[]> oldDataMap, boolean isRecover) {
		boolean result = false;
		int index = -1;
		try {
			if(path != null && (index = path.lastIndexOf("/")) != -1 && !"/".equals(path)) {
				String parentpath = path.substring(0, index);
				if(parentpath != null && parentpath.length() > 0 && zk.exists(parentpath, false) == null) {
					result = recoverAllNode(zk, parentpath, null, createOkMap, oldDataMap, false);
					if (!result) {
						return result;
					}
				}
				
				if (isRecover && zk.exists(path, false) != null) {
					byte[] oldData = getNodeByte(zk, path, false, null);
					zk.setData(path, content, -1);
					if(oldDataMap != null) {
						oldDataMap.put(path, oldData);
					}
				} else {
					zk.create(path, content, Ids.OPEN_ACL_UNSAFE,
							CreateMode.PERSISTENT);
					if (createOkMap != null) {
						createOkMap.put(path, content);
					}
				}
			}
			result = true;
		} catch (KeeperException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		} catch (InterruptedException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		}
		return result;
	}
	
	/**
	 * 根据mpa提供的path->value数据还原所有节点数据
	 * @param zk
	 * @param map
	 * @return
	 */
	public static boolean recoverAllNodeByMap(ZooKeeper zk, Map<String, String> map) {
		boolean result = false;
		if(map != null && map.size() > 0) {
			Map<String, byte[]> createOkMap = new TreeMap<>();
			Map<String, byte[]> oldDataMap = new TreeMap<>();
			for(String key:map.keySet()) {
				String val = map.get(key);
				byte[] content = val!=null?val.getBytes(Constants.defualtCharset):null;
				result = recoverAllNode(zk, key, content, createOkMap, oldDataMap, true);
				if(!result) {
					break;
				}
			}
			if (!result) {
				deleteAllNodeByMap(zk, createOkMap);
				setNodeDataByMap(zk, oldDataMap);
			} else {
				result = true;
			}
		}
		return result;
	}
	
	/**
	 * 读入一个节点及其路径下的所有内容
	 * @param zk
	 * @param path
	 * @param map
	 * @param replacePath
	 * @param isRename
	 */
	public static void readNode(ZooKeeper zk, String path, Map<String, byte[]> map, String replacePath, boolean isRename){
		if (existsNode(zk, path, false) != null) {
			byte[] data = getNodeByte(zk, path, false, null);
			int i = path.lastIndexOf("/");
			if(replacePath != null && replacePath.length() > 0 && i != -1) {
				if(!isRename) {
					replacePath = ZkCom.getZkEndPath(replacePath) + path.substring(i+1);
				}
				if (map != null) {
					map.put(replacePath, data);
				}
			}
			
			List<String> childrens = getChildren(zk, path, false);
			if (childrens != null && childrens.size() > 0) {
				path = "/".equals(path)?"/":(path+"/");
				replacePath = "/".equals(replacePath)?"/":(replacePath+"/");
				for(String c:childrens) {
					readNode(zk, path + c, map, isRename?replacePath+c:replacePath, isRename);
				}
			}
		}	
	}
	
	/**
	 * 重命名一个节点，失败回滚数据
	 * @param zk
	 * @param oldPath
	 * @param newPath
	 * @return
	 */
	public static boolean renameNode(ZooKeeper zk, String oldPath, String newPath){
		Map<String, byte[]> map = new TreeMap<>();
		Map<String, byte[]> okMap = new TreeMap<>();
		readNode(zk, oldPath, map, newPath, true);
		if (createAllNodeByMap(zk, map, okMap) == true) {
			deleteAllNode(zk, oldPath);
			return true;
		} else {
			deleteAllNodeByMap(zk, okMap);
			return false;
		}
	}
	
	/**
	 * 复制一个节点粘贴到目标路径下，失败回滚数据
	 * @param zk
	 * @param path
	 * @param targetPath
	 * @return
	 */
	public static boolean copyPasteNode(ZooKeeper zk, String path, String targetPath){
		Map<String, byte[]> map = new TreeMap<>();
		Map<String, byte[]> okMap = new TreeMap<>();
		readNode(zk, path, map, targetPath, false);
		if (createAllNodeByMap(zk, map, okMap) == true) {
			return true;
		} else {
			deleteAllNodeByMap(zk, okMap);
			return false;
		}
	}
	
	/**
	 * 剪切一个节点粘贴到目标路径下，失败回滚数据
	 * @param zk
	 * @param path
	 * @param targetPath
	 * @return
	 */
	public static boolean cutPasteNode(ZooKeeper zk, String path, String targetPath){
		Map<String, byte[]> map = new TreeMap<>();
		Map<String, byte[]> okMap = new TreeMap<>();
		readNode(zk, path, map, targetPath, false);
		if (createAllNodeByMap(zk, map, okMap) == true) {
			deleteAllNode(zk, path);
			return true;
		} else {
			deleteAllNodeByMap(zk, okMap);
			return false;
		}
	}
	
	/**
	 * 设置节点数据
	 * @param zk
	 * @param path
	 * @param content
	 * @return
	 */
	public static boolean setNodeData(ZooKeeper zk, String path, String content) {
		boolean result = false;
		byte[] b = content == null?null:content.getBytes(Constants.defualtCharset);
		try {
			zk.setData(path, b, -1);
			result = true;
		} catch (KeeperException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		} catch (InterruptedException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		}
		return result;
	}
	
	/**
	 * 设置节点数据
	 * @param zk
	 * @param path
	 * @param content
	 * @return
	 */
	public static boolean setNodeData(ZooKeeper zk, String path, byte[] content) {
		boolean result = false;
		try {
			zk.setData(path, content, -1);
			result = true;
		} catch (KeeperException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		} catch (InterruptedException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		}
		return result;
	}
	
	
	/**
	 * 设定map里记录的path->value的值
	 * @param zk
	 * @param map
	 * @return
	 */
	public static boolean setNodeDataByMap(ZooKeeper zk, Map<String, byte[]> map) {
		if(map != null && map.size() > 0) {
			for(String key:map.keySet()) {
				if(!setNodeData(zk, key, map.get(key))) {
					return false;
				}
			}
		}
		return true;
	}
	
	/**
	 * 读取指定节点和节点下的所有数据，提供Map对象数据用于备份数据
	 * @param zk
	 * @param fileValue
	 * @param path
	 */
	public static void readForBackup(ZooKeeper zk, Map<String, String> fileValue, String path){
		if (existsNode(zk, path, false) != null) {
			String data = getNodeData(zk, path);
			if(fileValue != null) {
				fileValue.put(path, data);
			} else {
				return;
			}
			
			List<String> childrens = getChildren(zk, path, false);
			if (childrens != null && childrens.size() > 0) {
				path = "/".equals(path)?"/":(path+"/");
				for(String c:childrens) {
					readForBackup(zk, fileValue, path+c);
				}
			}
		}
	}
	
	/**
	 * 备份一个指定节点和节点下的所有数据到指定目录，存储于叫节点名_时间戳的文件目录里
	 * @param zk
	 * @param path
	 * @param backupDirPath
	 * @param zkRootPath
	 * @return
	 */
	public static boolean backup(ZooKeeper zk, String path, File backupFile) {
		boolean result = false;
		Map<String, String> fileValue = new TreeMap<>();
		String zkPath = ZkCom.getZkPath(path);
		readForBackup(zk, fileValue, zkPath);
		if (fileValue.size() == 0) {
			logger.error("the zookeeper path(" + path + ") is not exists.");
			return result;
		}
		Kryo kryo = new Kryo();
		try {
			Output output = new Output(new FileOutputStream(backupFile));
			kryo.register(TreeMap.class);
			kryo.writeObject(output, fileValue);
		    output.close();
		    result = true;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			logger.error("the backup file isn't exists. (backupFile=" + backupFile.getAbsolutePath() + ")");
			logger.error(e.getMessage());
		}
		
		if(!result) {
			ComUtil.deleteFolder(backupFile);
		}
		
		return result;
	}
	
	/**
	 * 根据指定备份文件目录，还原相关节点数据
	 * @param zk
	 * @param procjetBackupDirPath
	 * @return
	 */
	public static boolean recover(ZooKeeper zk, String procjetBackupFile) {
		boolean result = false;
		Kryo kryo = new Kryo();
		try {
			Input input = new Input(new FileInputStream(procjetBackupFile));
			kryo.register(TreeMap.class);
			TreeMap<String, String> fileValue = kryo.readObject(input, TreeMap.class);
		    input.close();
		    result = recoverAllNodeByMap(zk, fileValue);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			logger.error("the backup file isn't exists. (backupFile=" + procjetBackupFile + ")");
		}		
		return result;
	}
	
	/**
	 * 获得节点内容
	 * @param zk
	 * @param path
	 * @return
	 */
	public static String getNodeData(ZooKeeper zk, String path) {
		String str = "";
		byte[] bytes = getNodeByte(zk, path, false, null);
		if(bytes != null) {
			str = new String(bytes, Constants.defualtCharset);
		}
		return str;
	}
	
	/**
	 * 获得节点内容
	 * @param zk
	 * @param path
	 * @param charset
	 * @return
	 */
	public static String getNodeData(ZooKeeper zk, String path, Charset charset) {
		String str = "";
		byte[] bytes = getNodeByte(zk, path, false, null);
		if(bytes != null) {
			if(charset != null) {
				str = new String(bytes, charset);
			} else {
				str = new String(bytes);
			}
		}
		return str;
	}
	
	/**
	 * 获得节点数据
	 * @param zk
	 * @param path
	 * @param watch
	 * @param stat
	 * @param charset
	 * @return
	 */
	public static String getNodeData(ZooKeeper zk, String path, boolean watch, Stat stat, Charset charset) {
		String str = "";
		byte[] bytes = getNodeByte(zk, path, watch, stat);
		if(bytes != null) {
			if(charset != null) {
				str = new String(bytes, charset);
			} else {
				str = new String(bytes);
			}
		}
		return str;
	}
	
	/**
	 * 获得节点数据
	 * @param zk
	 * @param path
	 * @param watch
	 * @param stat
	 * @return
	 */
	public static byte[] getNodeByte(ZooKeeper zk, String path, boolean watch, Stat stat) {
		try {
			return zk.getData(path, watch, stat);
		} catch (KeeperException | InterruptedException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		}
		return null;
	}
	
	/**
	 * 获取指定路径下的子节点
	 * @param zk
	 * @param path
	 * @return
	 */
	public static List<String> getChildren(ZooKeeper zk, String path) {
		List<String> list = null;
		try {
			list = zk.getChildren(path, false);
		} catch (KeeperException | InterruptedException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		}
		return list;
	}
	
	/**
	 * 获取指定路径下的子节点
	 * @param zk
	 * @param path
	 * @param watch
	 * @return
	 */
	public static List<String> getChildren(ZooKeeper zk, String path, boolean watch) {
		List<String> list = null;
		try {
			list = zk.getChildren(path, watch);
		} catch (KeeperException | InterruptedException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		}
		return list;
	}
	
	/**
	 * 判断节点是否存在
	 * @param zk
	 * @param path
	 * @param watch
	 * @return
	 */
	public static Stat existsNode(ZooKeeper zk, String path, boolean watch) {
		Stat stat = null;
		try {
			stat = zk.exists(path, watch);
		} catch (KeeperException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		} catch (InterruptedException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		}
		return stat;
	}
	
	/**
	 * 判断节点是否存在
	 * @param zk
	 * @param path
	 * @return
	 */
	public static Stat existsNode(ZooKeeper zk, String path) {
		Stat stat = null;
		try {
			stat = zk.exists(path, false);
		} catch (KeeperException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		} catch (InterruptedException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		}
		return stat;
	}
	
	/**
	 * 上传本地的目录下某个文件或所有文件到某个节点下，失败提供回滚数据的map
	 * @param zk
	 * @param file
	 * @param nodePath
	 * @param createOkMap
	 * @param oldDataMap
	 * @param isFirst
	 * @return
	 */
	private static boolean uploadFile(ZooKeeper zk, File file, String nodePath, Map<String, byte[]> createOkMap, Map<String, byte[]> oldDataMap, boolean isFirst) {
		boolean result = false;
		String fileContent = null;
		if(file.isDirectory()) {
			File[] fileList = file.listFiles();
			for(File cfile:fileList) {
				String path = "/".equals(nodePath)?("/"+cfile.getName()):(nodePath+"/"+cfile.getName());
				if(cfile.isDirectory()) {
					result = uploadFile(zk, cfile, path, createOkMap, oldDataMap, false);
				} else {
					result = uploadFile(zk, cfile, path, createOkMap, oldDataMap, false);
				}
				
				if (!result) return result;
			}
		} else {
			fileContent = ComUtil.readFile(file);
		}
		if(!isFirst) {
			logger.debug("upload file="+file.getName());
			byte[] content = fileContent == null?null:fileContent.getBytes(Constants.defualtCharset);
			if(existsNode(zk, nodePath) == null) {
				if(createAllNode(zk, nodePath, content)) {
					createOkMap.put(nodePath, content);
				} else {
					return false;
				}
			} else {
				byte[] oldData = getNodeByte(zk, nodePath, false, null);
				if (setNodeData(zk, nodePath, content)) {
					oldDataMap.put(nodePath, oldData);
				} else {
					return false;
				}
			}
			result = true;
		}
		
		return result;
	}
	
	/**
	 * 上传本地的目录下某个文件或所有文件到某个节点下，失败回滚数据
	 * @param zk
	 * @param file
	 * @param nodePath
	 * @return
	 */
	public static boolean uploadFile(ZooKeeper zk, File file, String nodePath) {
		if (file == null || !file.exists()) {
			logger.error("the upload file is not exists.");
			return false;
		}
		nodePath = ZkCom.getZkPath(nodePath);
		Map<String, byte[]> createOkMap = new TreeMap<>();
		Map<String, byte[]> oldDataMap = new TreeMap<>();
		boolean result = uploadFile(zk, file, nodePath, createOkMap, oldDataMap, true);
		if (!result) {
			deleteAllNodeByMap(zk, createOkMap);
			setNodeDataByMap(zk, oldDataMap);
		}
		return result;
	}
	
	/**
	 * 下载某个节点下的文件到指定的目录下，忽略文件夹节点的数据
	 * @param zk
	 * @param file
	 * @param nodePath
	 * @return
	 */
	public static boolean downloadFile(ZooKeeper zk, File filedir, String nodePath) {
		if(filedir == null) {
			logger.error("The download diretory is not exists.");
			return false;
		}
		if(!filedir.exists()) {
			if(!filedir.mkdirs()) {
				logger.error("Create download diretory is fail. file="+filedir.getAbsolutePath());
				return false;
			}
		}
		if(!filedir.isDirectory()) {
			logger.error("The download file is not diretory. file="+filedir.getAbsolutePath());
			return false;
		}
		boolean result = false;
		String zkPath = ZkCom.getZkPath(nodePath); 
		List<String> childrens = getChildren(zk, zkPath, false);
		String fileName = zkPath.substring(zkPath.lastIndexOf("/")+1).replaceAll(":|\\*|\\?|\"|\\||<|>", "");
		File file = new File(filedir.getAbsolutePath()+"/"+fileName);
		if (childrens != null && childrens.size() > 0) {
			if(!file.exists()) {
				if(!file.mkdirs()) {
					logger.error("Create download diretory is fail. file="+file.getAbsolutePath());
					return false;
				}
			}
			zkPath = "/".equals(zkPath)?"/":(zkPath+"/");
			for(String c:childrens) {
				String filePath = file.getAbsolutePath()+"/"+c.replaceAll(":|\\*|\\?|\"|\\||<|>", "");
				result = downloadFileRecursive(zk, filePath, zkPath+c);
				if(!result) {
					return false;
				}
			}
		} else {
			String data = getNodeData(zk, zkPath);
			if(data != null && data.length() > 0) {
				result = ComUtil.writeFile(file, data);
			} else {
				if(!file.exists()) {
					if(!file.mkdirs()) {
						logger.error("Create download diretory is fail. file="+file.getAbsolutePath());
						return false;
					}
				}
				result = true;
			}
		}
		return result;
	}
	
	/**
	 * 下载节点及其下的文件到指定目录，忽略文件夹节点的数据
	 * @param zk
	 * @param filePath
	 * @param zkPath
	 * @return
	 */
	private static boolean downloadFileRecursive(ZooKeeper zk, String filePath, String zkPath) {
		boolean result = false;
		File file = new File(filePath);
		List<String> childrens = getChildren(zk, zkPath, false);
		if (childrens != null && childrens.size() > 0) {
			zkPath = "/".equals(zkPath)?"/":(zkPath+"/");
			if(!file.exists()) {
				if(!file.mkdirs()) {
					logger.error("Create download diretory is fail. file="+file.getAbsolutePath());
					return false;
				}
			}
			for(String c:childrens) {
				String filePath2 = file.getAbsolutePath()+"/"+c.replaceAll(":|\\*|\\?|\"|\\||<|>", "");
				result = downloadFileRecursive(zk, filePath2, zkPath+c);
				if(!result) {
					return false;
				}
			}
		} else {
			String data = getNodeData(zk, zkPath);
			if(data != null && data.length() > 0) {
				result = ComUtil.writeFile(file, data);
			} else {
				if(!file.exists()) {
					if(!file.mkdirs()) {
						logger.error("Create download diretory is fail. file="+file.getAbsolutePath());
						return false;
					}
				}
				result = true;
			}
		}
		return result;
	}
}
